/**
ProductDataImporter.java
business
2012-8-16下午3:09:52
@author 屈甲康
@QQ285799123
mailto:qujiakang@126.com
 **/
package org.jackysoft.report.data;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.jackysoft.entity.Department;
import org.jackysoft.entity.Product;
import org.jackysoft.entity.ProductQuota;
import org.jackysoft.entity.ProductType;
import org.jackysoft.entity.Technics;
import org.jackysoft.service.DepartmentService;
import org.jackysoft.service.ProductService;
import org.jackysoft.service.TechnicsService;
import org.jackysoft.util.ExcelUtil;
import org.springframework.util.Assert;

import com.google.common.collect.Lists;

/**
 * 用于导入产品数据
 **/

public class ProductDataImporter extends AbstractDataImporter {

	static final Log logger = LogFactory.getLog(ProductDataImporter.class);
	private ProductService productService;
	private TechnicsService techniService;

	private Map<String, Product> products;
	private Map<String, ProductQuota> quotas;
	private Collection<Technics> technicses;
    private DepartmentService  deptService;
	
	public ProductDataImporter(
			ProductService service,
			TechnicsService techniService,
			DepartmentService deptService
			) {
	
		this.productService = service;
		this.techniService  = techniService;
		this.deptService    = deptService;
	}

	
	@Override
	public List<String> fromStream(InputStream input, String deptName) {
		Assert.notNull(deptName, "部门名称不能为空");
		Assert.notNull(input, "文件不能为空");
		logger.info("准备导入 " + deptName + "的产品");
		products = new HashMap<String, Product>();
		quotas = new HashMap<String, ProductQuota>();
		technicses = Lists.newArrayList();
		Collection<Product> pdts = productService.gets();
		Set<String> filter = new HashSet<String>();
		for (Product pdt : pdts)
			filter.add(pdt.getCode());
		List<String> errorInfo = this.parseProductAndQuota(input, filter,
				deptName);

		if(errorInfo.size()>0){
			logger.error("由于数据格式发生错误,导入失败");
			logger.info("错误消息:");
			for(String error : errorInfo){
				logger.info(error);
			}
			return errorInfo;
		}
		
				
		productService.create(products.values());
		productService.createQuota(quotas.values());
		techniService.create(technicses);
		logger.info("导入成功进行");
		return errorInfo;
	}

	protected List<String> parseProductAndQuota(InputStream input,
			Set<String> filter, String deptName) {

		List<String> errorInfo = new ArrayList<String>();
		try {
			HSSFWorkbook workbook = new HSSFWorkbook(input);
			
			int sheetCount = workbook.getNumberOfSheets();

			for (int i = 0; i < sheetCount; i++) {

				HSSFSheet sheet = workbook.getSheetAt(i);

				Iterator<Row> rows = sheet.rowIterator();

				Product parent = null;				
				while (rows.hasNext()) {

					// logger.info("正在处理文件 "+file.getName()+"第"+rowIndex+"行...");
					Row row = rows.next();	
					int rowIndex = row.getRowNum();
					
					Iterator<Cell> cells = row.cellIterator();

					// 0 产品类型 * 表示为成品
					// 1 产品代码和名称用空格分隔
					// 2 产品定额无数字则为1
					// 3 生产厂家,成品则为本厂,半成品则为自制表示不下计划
					// 4 生产工艺

					Cell first = ExcelUtil.nextCell(cells);
                    
					String deptId = "";
					String startValue = "";
					try {
						startValue = StringUtils.trim(first.getStringCellValue());
					} catch (IllegalStateException e) {

						errorInfo.add(deptName + " line: " + rowIndex
								+ " 类型解析错误," + first.getNumericCellValue());

					}								
					if ("*".equals(startValue)) {
						Cell second = ExcelUtil.nextCell(cells);
						
						String codeName = StringUtils.trim(second
								.getStringCellValue());
						if (StringUtils.isBlank(codeName)) {
							errorInfo.add(deptName + " line: " + rowIndex+" 代码名称列为空");
							continue;
						}
						String[] ss = codeName.split("\\s+");
						if (ss == null || ss.length < 2) {
							errorInfo.add(deptName + " line: " + rowIndex+" 代码名称列空格数不正确，最多只能有一个");
							continue;
						}
						String code = StringUtils.trim(ss[0]);

						String name = ss[1];					
						
						//忽略空列
						ExcelUtil.nextCell(cells);
						
						//部门列
						Cell  third = ExcelUtil.nextCell(cells);
						Department dept = deptService.getByName(ExcelUtil.cellString(third));
						parent = new Product();
						parent.getProviders().add(dept);
						parent.setItemType(ProductType.常规产品);
						parent.setCode(code);
						parent.setName(name);

						if (filter.contains(code)) {

							parent = productService.get(code);

						} else {
							products.put(code, parent);
							// logger.info(parent);
						}
						
						
						continue;
                        //标识为星号的产品处理，并开始下一行扫描		
					}				
                   
					//消耗定额
					Cell second = first;
								
					if(StringUtils.isBlank(ExcelUtil.cellString(second))){
					   	second = ExcelUtil.nextCell(cells);
					   	startValue = ExcelUtil.cellString(second);
					}
						
					if(StringUtils.isBlank(ExcelUtil.cellString(second))){
						errorInfo.add(rowIndex+"行 :"+second.getColumnIndex()+"列应该为代码名称列，而当前为空");
						continue;
						
					}
						
				

					String[] ss = startValue.split("\\s+");
					if (ss == null || ss.length != 2) {
						errorInfo.add(rowIndex+"行:代码名称空格不匹配");
						
						continue;
					}

					String code = StringUtils.trim(ss[0]).toUpperCase();

					String name = ss[1];
					
					
					//消耗定额
					second = ExcelUtil.nextCell(cells);
								
					Double consume = second==null?1D:ExcelUtil.cellNumber(second);
					
					//部门列
					Cell third = ExcelUtil.nextCell(cells);

					String dname = ExcelUtil.cellString(third);

					if ("自制".equals(dname))continue;
				

					
					Department usedept = deptService.getByName(dname);
					logger.info("find department is : "+usedept +" with name "+dname);
					
				    deptId = usedept.getId();
				    logger.info("find department :"+dname +"@"+deptId);
					if (deptId == null) {
						errorInfo.add(rowIndex+"行:部门名称["+dname+"]没找到");
						continue;
					}
					Product pdt = new Product();

					pdt.setItemType(ProductType.部件);
					pdt.setCode(code);
					pdt.setName(name);					
					pdt.getProviders().add(usedept);

					if (filter.contains(code)) {
						pdt = productService.get(code);

					} else {
						products.put(code, pdt);
						logger.info("扫描产品:" + pdt);
					}

					

					ProductQuota oldQuota = productService.calculateQuota(
							parent, pdt);
					if (oldQuota != null) {
						oldQuota.setConsume(consume);
						productService.updateSingleQuota(oldQuota);
					} else {
						ProductQuota quota = new ProductQuota();
						quota.setHost(parent);
						quota.setOwner(pdt);
						quota.setConsume(consume);
						quotas.put(parent.getCode() + pdt.getCode(), quota);
						logger.info("扫描定额:" + quota);
					}
					// logger.info(quota);
					Cell fourth = ExcelUtil.nextCell(cells);
					if (fourth != null) {
						String tname = ExcelUtil.cellString(fourth);
						if (!StringUtils.isBlank(tname)) {
							Technics tec = techniService.get(usedept, pdt,
									tname);
							if (tec == null) {
								tec = new Technics();
								tec.setDepartment(usedept);
								tec.setProduct(pdt);
								tec.setName(tname);
								technicses.add(tec);
								logger.info("扫描工艺:" + pdt);
							}
						}

					}

					
				}
				logger.info("文件" + deptName + " 表:" + sheet.getSheetName()
						+ "完成");
			}
			logger.info("解析文件 " + deptName + " 完成");
		} catch (IOException e) {
			e.printStackTrace();
		}
		return errorInfo;
	}	
	
}
